package bamboo.Modern_Java_in_Action.chap7;

/**
 * @Author: fulw
 * @Date: 2022/2/18 17:31
 */
public class ForkJoinSumCalculator
        extends java.util.concurrent.RecursiveTask<Long> {       // 扩展RecursiveTask来创建可以用于分支/合并框架的任务
    private final long[] numbers;       // 要求和的数字数组
    private final int start;       // 由子任务处理的子数组的起始和终止位置
    private final int end;
    public static final long THRESHOLD = 10_000;       // 将任务分解为子任务的阈值大小

    public ForkJoinSumCalculator(long[] numbers) {       // 公共构造函数用于创建主任务
        this(numbers, 0, numbers.length);
    }

    private ForkJoinSumCalculator(long[] numbers, int start, int end) {       // 私有构造函数用于以递归方式为主任务创建子任务
        this.numbers = numbers;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {       // 重写RecursiveTask抽象方法
        int length = end - start;       // 该任务负责求和的子数组大小
        if (length <= THRESHOLD) {
            return computeSequentially();       // 如果大小小于或等于阈值，就顺序计算结果
        }
        ForkJoinSumCalculator leftTask =
                new ForkJoinSumCalculator(numbers, start, start + length / 2);       // 创建一个子任务来为数组的前一半求和
        leftTask.fork();       // 利用ForkJoinPool的另一个线程异步地执行新创建的子任务
        ForkJoinSumCalculator rightTask =
                new ForkJoinSumCalculator(numbers, start + length / 2, end);

        //    任务来为数组的后一半求和
        Long rightResult = rightTask.compute();       // 同步执行第二个子任务，有可能进行进一步的递归划分
        Long leftResult = leftTask.join();       // 读取第一个子任务的结果，如果尚未完成就等待
        return leftResult + rightResult;       // 整合两个子任务的计算结果
    }

    private long computeSequentially() {       // 大小小于阈值时所采用的一个简单的顺序算法
        long sum = 0;
        for (int i = start; i < end; i++) {
            sum += numbers[i];
        }
        return sum;
    }
}
